!-------------------------------------------------------------LICENSE--------------------------------------------------------------!
!                                                                                                                                  !
!The MAP code is written in Fortran language for magnetohydrodynamics (MHD) calculation with the adaptive mesh refinement (AMR)    !
!and Message Passing Interface (MPI) parallelization.                                                                              !
!                                                                                                                                  !
!Copyright (C) 2012                                                                                                                !
!Ronglin Jiang                                                                                                                     !
!rljiang@ssc.net.cn                                                                                                                !
!585 Guoshoujing Road. Pudong, Shanghai, P.R.C. 201203                                                                             !
!                                                                                                                                  !
!This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License         !
!as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.             !
!                                                                                                                                  !
!This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of    !
!MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.                        !
!                                                                                                                                  !
!You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software     !
!Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.                                                   !
!                                                                                                                                  !
!-------------------------------------------------------------LICENSE--------------------------------------------------------------!

!==================================================================================================================================|
subroutine save_state(base)
!==================================================================================================================================|

   use parameters
   use block_define
   implicit none

   type(block), pointer, intent(in) :: base

   character(4) :: n_save_state_char, cpu_char
   integer(4) :: n_gene_output, gene_output(n_dims, n_levels, n_blocks_all)
   type(block), pointer :: current

!----------------------------------------------------------------------------------------------------------------------------------|
   write(n_save_state_char,'(i4.4)') n_save_state
   write(cpu_char,'(i4.4)') cpu_id

   n_gene_output = 0
   current => base%framework_next
   do while (current%lv .ne. 0)
      n_gene_output = n_gene_output + 1
      gene_output(:, :, n_gene_output) = current%id
      current => current%framework_next
   enddo

   open(unit_save_state, file = trim(datamap_path) // 'state.n' // n_save_state_char // '.cpu' // cpu_char // '.mapout',           &
      form = 'unformatted')

   write(unit_save_state) cpu_number
   write(unit_save_state) max_speed
   write(unit_save_state) max_et
   write(unit_save_state) max_te_ro
   write(unit_save_state) min_dt
   write(unit_save_state) min_dt_hc
   write(unit_save_state) max_level
   write(unit_save_state) ns
   write(unit_save_state) nt
   write(unit_save_state) t
   write(unit_save_state) t_regrid
   write(unit_save_state) base%dt
   write(unit_save_state) base%t
   write(unit_save_state) n_save_state
   write(unit_save_state) n_blocks
   write(unit_save_state) n_blocks_all
   write(unit_save_state) n_gene_output
   write(unit_save_state) gene_output(:, :, 1:n_gene_output)
   write(unit_save_state) hilbert_start
   write(unit_save_state) hilbert_end
   write(unit_save_state) reflux_size_x
   write(unit_save_state) reflux_size_y
   write(unit_save_state) reflux_size_z
   write(unit_save_state) shareblock_size_x
   write(unit_save_state) shareblock_size_y
   write(unit_save_state) shareblock_size_z
   write(unit_save_state) exchange_size_x
   write(unit_save_state) exchange_size_y
   write(unit_save_state) exchange_size_z
   write(unit_save_state) reflux_size_send_x
   write(unit_save_state) reflux_size_recv_x
   write(unit_save_state) reflux_size_send_y
   write(unit_save_state) reflux_size_recv_y
   write(unit_save_state) reflux_size_send_z
   write(unit_save_state) reflux_size_recv_z
   write(unit_save_state) shareblock_size_send_x
   write(unit_save_state) shareblock_size_recv_x
   write(unit_save_state) shareblock_size_send_y
   write(unit_save_state) shareblock_size_recv_y
   write(unit_save_state) shareblock_size_send_z
   write(unit_save_state) shareblock_size_recv_z
   write(unit_save_state) exchange_size_send_x
   write(unit_save_state) exchange_size_recv_x
   write(unit_save_state) exchange_size_send_y
   write(unit_save_state) exchange_size_recv_y
   write(unit_save_state) exchange_size_send_z
   write(unit_save_state) exchange_size_recv_z
   write(unit_save_state) n_neighs_reflux_sendrecv_x
   write(unit_save_state) n_neighs_reflux_sendrecv_y
   write(unit_save_state) n_neighs_reflux_sendrecv_z
   write(unit_save_state) n_neighs_shareblock_sendrecv_x
   write(unit_save_state) n_neighs_shareblock_sendrecv_y
   write(unit_save_state) n_neighs_shareblock_sendrecv_z
   write(unit_save_state) n_neighs_exchange_sendrecv_x
   write(unit_save_state) n_neighs_exchange_sendrecv_y
   write(unit_save_state) n_neighs_exchange_sendrecv_z
   write(unit_save_state) neighs_reflux_info_send_x
   write(unit_save_state) neighs_reflux_info_send_y
   write(unit_save_state) neighs_reflux_info_send_z
   write(unit_save_state) neighs_shareblock_info_send_x
   write(unit_save_state) neighs_shareblock_info_send_y
   write(unit_save_state) neighs_shareblock_info_send_z
   write(unit_save_state) neighs_exchange_info_send_x
   write(unit_save_state) neighs_exchange_info_send_y
   write(unit_save_state) neighs_exchange_info_send_z

   current => base%framework_next
   do while (current%lv .ne. 0)
      write(unit_save_state) current%id
      write(unit_save_state) current%x
      write(unit_save_state) current%y
      write(unit_save_state) current%z
      write(unit_save_state) current%cpu_id
      write(unit_save_state) current%dx
      write(unit_save_state) current%dy
      write(unit_save_state) current%dz
      write(unit_save_state) current%dt
      write(unit_save_state) current%t
      write(unit_save_state) current%var_allocate_flag

      if (current%var_allocate_flag) then
         write(unit_save_state) current%ro
         write(unit_save_state) current%mx
         write(unit_save_state) current%my
         write(unit_save_state) current%mz
         write(unit_save_state) current%bx
         write(unit_save_state) current%by
         write(unit_save_state) current%bz
         write(unit_save_state) current%en
         write(unit_save_state) current%gx
         write(unit_save_state) current%gy
         write(unit_save_state) current%gz
         write(unit_save_state) current%po

         if (ini_value_save_flag .ne. 0) then
            write(unit_save_state) current%ro0
            write(unit_save_state) current%mx0
            write(unit_save_state) current%my0
            write(unit_save_state) current%mz0
            write(unit_save_state) current%bx0
            write(unit_save_state) current%by0
            write(unit_save_state) current%bz0
            write(unit_save_state) current%en0
         endif
      endif

      current => current%framework_next
   enddo
   close(unit_save_state)

!----------------------------------------------------------------------------------------------------------------------------------|
   return
end subroutine save_state
